package com.wh1200.mybatis.xmlless.model

import com.wh1200.mybatis.xmlless.AnnotatedElementDetailInfo
import com.wh1200.mybatis.xmlless.annotations.DeleteValue
import com.wh1200.mybatis.xmlless.enums.QueryType
import com.wh1200.mybatis.xmlless.enums.XmllessDbType
import com.wh1200.mybatis.xmlless.model.base.BaseXmllessMethodWrapper
import com.wh1200.mybatis.xmlless.model.criteria.OptionalParam
import com.wh1200.mybatis.xmlless.model.criteria.ParameterInfo

/**
 * 方法信息
 *
 * @author 吴昊
 * @date 2023/12/7 11:37
 * @since v4.0.0
 * @version 1.0
 */
class MethodInfo(
    val modelName: String,
    val modelFields: List<AnnotatedElementDetailInfo>,
    val returnType: Class<*>?,
    val mappings: FieldMappingList,
    val modelMappings: FieldMappingList,
    val dbType: XmllessDbType,
    val fullMethodName: String,
    /** 属性到指定sql表达式的映射 */
    val propertiesMapping: Map<String, String>,
    val isJsonResult: Boolean,
    val resultMap: List<String>,
    val excludeProperties: List<String>,
    val selectedProperties: List<String>,
    val name: String,
    val isLogic: Boolean,
    /** 方法参数列表 */
    val parameters: List<ParameterInfo>,
    val paramNames: Array<String>,
    xmllessMethod: BaseXmllessMethodWrapper,
    /** 可选参数列表 */
    private val optionalParameters: List<OptionalParam>
) {

  val tableInfo = mappings.tableInfo
  val queryType: QueryType? = xmllessMethod.getType()
  val sorts: List<String> = xmllessMethod.getSorts()
  val conditions: List<String> = xmllessMethod.getConditions()
  val updateSetList: List<String> = xmllessMethod.getUpdateSetList()
  val groupBy: List<String> = xmllessMethod.getGroupBys()
  val limit: String? = xmllessMethod.getLimit()
  val scriptAppend: String = xmllessMethod.getScriptAppend()
  val joinAppend: String = xmllessMethod.getJoinAppend()
  val whereAppend: String = xmllessMethod.getWhereAppend()
  val includes: List<String> = xmllessMethod.getIncludes()
  val ignoreIfWrapFields: List<String> = xmllessMethod.getIgnoreIfWrapFields()
  val excludes: List<String> = xmllessMethod.getExcludes()

  val hasOnlyComplexParameter = parameters.size == 1 && parameters.first().isComplex

  init {
    if (includes.isNotEmpty() && updateSetList.isNotEmpty()) {
      error("方法${fullMethodName}不能同时使用@XmllessMethod的includes和updateSet属性")
    }
  }


  fun findOptionalParam(property: String): OptionalParam? {
    return optionalParameters.firstOrNull { it.name() == property || it.name == property }
  }

  fun createLogicCriteria(): QueryCriteria {
    val logicFieldInfo = tableInfo.logicDeleteFieldInfo
      ?: error(
          "持久化类${modelName}缺少逻辑删除字段，请在字段上添加@TableLogic注解"
      )
    val specificValue = mappings.getLogicDelFlagValue(DeleteValue.NotDeleted)
    return LogicDeleteCriteria(
        logicFieldInfo.property,
        methodInfo = this,
        specificValue = if (specificValue is String) {
          SpecificValue(
              stringValue = specificValue,
              nonStringValue = ""
          )
        } else {
          SpecificValue(
              stringValue = "",
              nonStringValue = specificValue.toString()
          )
        }
    )
  }

  fun findMapping(property: String): FieldMapping? {
    return mappings.mappings.find {
      it.property == property
    } ?: modelMappings.mappings.find {
      it.property == property
    }
  }

}
